package com.lins.storedisk.config.advice;

import cn.dev33.satoken.util.SaResult;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lins.disk.common.APIException;
import com.lins.disk.common.AppCode;
import com.lins.disk.config.annotation.NotControllerResponseAdvice;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * 统一处理包下的响应 建议
 * @Author linshuo
 * @Date 2023/12/1 13:13
 */
@RestControllerAdvice(basePackages = {"com.lins.disk.controller"})//统一处理包下的响应
public class ControllerResponseAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        //若响应已经包装，或被注解修饰 则返回false 不再包装处理
//        return !(methodParameter.getParameterType().isAssignableFrom(SaResult.class) ||
//                        methodParameter.hasMethodAnnotation(NotControllerResponseAdvice.class));

        Class<?> type = methodParameter.getParameterType();
        boolean a = false;
        if (null != type){
//            a = type.isAssignableFrom(SaResult.class);
            a = type.equals(SaResult.class);
        }
        boolean b = methodParameter.hasMethodAnnotation(NotControllerResponseAdvice.class);
        boolean r = !(a||b);
        return r;
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType,
                                  Class<? extends HttpMessageConverter<?>> aClass,
                                  ServerHttpRequest request, ServerHttpResponse response) {
        // 方法返回类型 是String类型 不能直接包装
        if (methodParameter.getGenericParameterType().equals(String.class)) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                return objectMapper.writeValueAsString(SaResult.data(o)); // 将数据 包装后 转json
            } catch (JsonProcessingException e) {
                throw new APIException(AppCode.APP_ERROR, e.getMessage());
            }
        }
        // 非字符串 直接包装成 返回
        SaResult data = SaResult.data(o);
        return data;

        /**
         * 这里的json对象，会被spring mvc的HttpMessageConverter再次转换为String json
         * 在系列化过程中 会导致Integer转String失败，抛出异常。
         * 关于spring mvc源码分析参考【http://www.manongjc.com/detail/57-gxliooajrvvswlx.html】
         **/
    }
}
